home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / asm_n_z.zip / WC.ASM < prev    next >
Assembly Source File  |  1989-03-20  |  10KB  |  320 lines

  1. cseg    segment
  2.     org 100h
  3.     assume ds:cseg, cs:cseg
  4. ;================================================
  5. ; PROGRAM WC    Version 1.1 by Dave Whitman
  6. ;
  7. ; Filter to count words, lines and characters.
  8. ; Based loosely on Kernighan and Ritchie, page 18.
  9. ;
  10. ; Syntax:  WC [/w] [/l] [/c]
  11. ;
  12. ;          /w = unlabeled word count
  13. ;          /l = unlabeled line count
  14. ;          /c = unlabeled character count
  15. ;        none = combined counts, with labels
  16. ;
  17. ; The three options may be present in any combination.
  18. ; Regardless of option order, the selected counts will
  19. ; be in the following order:
  20. ;    words
  21. ;    lines
  22. ;    characters
  23. ;
  24. ; Requires DOS 2.0, will abort under earlier versions.
  25. ;====================================================
  26.  
  27. ;============
  28. ; Equates
  29. ;============
  30.  
  31. @read   equ    3FH             ;read file/device
  32. @chrin  equ    06H             ;get char from stdin
  33. @chrout equ    02H             ;send char to stdout
  34. @dosver equ    30H             ;get dos version
  35. @prnstr equ    09H             ;print string
  36.  
  37. stdin   equ    0000H           ;standard input
  38. w       equ    01H             ;flag value for word option
  39. l       equ    02H             ;flag value for line option
  40. c       equ    04H             ;flag value for char option
  41. yes     equ    0FFH            ;boolean value
  42. no      equ    00H             ;    "
  43. bsn      equ    0DH             ;newline char
  44. bst      equ    09H             ;tab char
  45. bsl      equ    0AH             ;linefeed char
  46.  
  47. param_count    equ     [80H]
  48. param_area     equ     [81H]
  49.  
  50. main   proc    far
  51.        call    setup           ;check dos, parse options
  52.        call    buf_in          ;count w, l, c from std i/o
  53.        call    output          ;send requested output
  54.        int     20H             ;and return to dos
  55. main   endp
  56.  
  57. ;======================================
  58. ; SUBROUTINE SETUP
  59. ; Checks for proper DOS, parses options
  60. ;======================================
  61. setup  proc    near
  62.  
  63.        mov     ah, @dosver     ;what dos are we under?
  64.        int     21H
  65.        cmp     al, 2           ;2.0 or over?
  66.        jae     a1              ;yes, skip
  67.  
  68.        mov     ah, @prnstr     ;no, bitch
  69.        mov     dx, offset(baddos)
  70.        int     21H
  71.        pop     ax              ;reset stack
  72.        int     20H             ;and exit
  73.  
  74. a1:     xor     ch,ch           ;cx <== param count
  75.        mov     cl, param_count ;  "
  76.        cmp     cl, 00H         ;any params?
  77.        je      aexit           ;exit if none
  78.  
  79.        mov     di, offset(param_area)   ;scan for options
  80. a2:     mov     al, '/'                  ;will be marked with /
  81.        repnz
  82.        scasb
  83.        jnz     aexit           ;reached end
  84.  
  85.        mov     al, [di]        ;get option char
  86.        and     al, 0DFH        ;guarantees upper case
  87.  
  88.        cmp     al, 'W'         ;words?
  89.        jne     a3              ;nope
  90.        orb     options, w      ;yes, set flag
  91.        jmps    a2              ;and loop
  92.  
  93. a3:     cmp     al, 'L'         ;lines?
  94.        jne     a4              ;nope
  95.        orb     options, l      ;yes, set flag
  96.        jmps    a2              ;and loop
  97.  
  98. a4:     cmp     al, 'C'         ;characters?
  99.        jne     a2              ;nope, just loop
  100.        orb     options, c      ;yes, set flag
  101.        jmps    a2              ;and loop
  102.  
  103. aexit:  ret
  104.  
  105. baddos db      'This program requires DOS 2.0!' 0DH, 0AH, '$'
  106. setup    endp
  107.  
  108. ;=========================================
  109. ; SUBROUTINE BUF_INPUT
  110. ; Inputs data by sector, sends it one char
  111. ; at a time for counting.
  112. ;==========================================
  113.  
  114.  
  115. buf_in proc    near
  116.  
  117.        movb    inword, no      ;not currently in a word
  118.  
  119. bu1:    mov     ah, @read       ;read
  120.        mov     bx, stdin       ;from stdin
  121.        mov     cx, 512         ;one sector's worth
  122.        mov     dx, offset(buffer)
  123.        int     21H
  124.        cmp     ax, 00H         ;test for EOF
  125.        jz      buexit          ;if so, done
  126.  
  127.        mov     cx,ax           ;cx <== number chars read
  128.        mov     si, offset(buffer)
  129. bu2:    lodsb                   ;al <== next char from buffer
  130.        call    count           ;update totals
  131.        loop    bu2
  132.        jmps    bu1
  133. buexit: ret
  134. buf_in    endp
  135.  
  136. ;=============================================
  137. ;SUBROUTINE COUNT
  138. ;Counts words, lines and characters as per K&R
  139. ;=============================================
  140. count  proc    near
  141.        addw    clow,0001H      ;bump # of chars
  142.        jae     b1              ;no carry? skip
  143.        incw    chigh           ;handle carry
  144.  
  145.        ;in the following, note use of ADD to increment
  146.        ;doublewords.  INC does not affect Carry Flag.
  147.  
  148. b1:     cmp     al, bsn          ;is it a newline?
  149.        jne     b2              ;no, skip
  150.        addw    llow,0001H      ;bump # of lines
  151.        jae     b2              ;no carry? skip
  152.        incw    lhigh           ;handle carry
  153.  
  154. b2:     cmp     al, bsn          ;newline or
  155.        je      b3
  156.        cmp     al, bst          ;tab or
  157.        je      b3
  158.        cmp     al, bsl          ;linefeed or
  159.        je      b3
  160.        cmp     al, ' '         ;blank,
  161.        je      b3              ;then skip
  162.  
  163.       ;none of the above
  164.        cmpb    inword, yes     ;already in a word?
  165.        je      b4              ;yes, return
  166.        movb    inword, yes     ;if not, we are now.
  167.        addw    wlow,0001H      ;bump word count
  168.        jae     b4              ;no carry? return
  169.        incw    whigh           ;handle carry
  170.        jmps    b4              ;return
  171.  
  172.       ;any of the above
  173. b3:     movb    inword, no
  174. b4:     ret
  175. count    endp
  176.  
  177. ;=====================================
  178. ; SUBROUTINE OUTPUT
  179. ; Prints results, modified by options.
  180. ;=====================================
  181. output proc    near
  182.  
  183.        cmpb    options, 00H    ;any options?
  184.        jne     c1              ;yes, skip label
  185.        mov     ah, @prnstr     ;print label for word count
  186.        mov     dx, offset(word_label)
  187.        int     21H
  188.        jmps    c1a             ;print count
  189.  
  190. c1:     testb   options, W      ;/w option?
  191.        jz      c2              ;nope, skip
  192. c1a:    mov     di, whigh       ;get doubleword word count
  193.        mov     si, wlow        ; in di:si
  194.        call    printdd         ;convert and print it.
  195.        call    newline
  196.  
  197. c2:     cmpb    options, 00H    ;any options?
  198.        jne     c3              ;yes, skip label
  199.        mov     ah, @prnstr     ;print label for line count
  200.        mov     dx, offset(line_label)
  201.        int     21H
  202.        jmps    c3a             ;print count
  203.  
  204. c3     testb   options, L      ;/l option?
  205.        jz      c4              ;nope, skip
  206. c3a    mov     di, lhigh       ;get doubleword line count
  207.        mov     si, llow        ; in di:si
  208.        call    printdd         ;convert and print it
  209.        call    newline
  210.  
  211. c4:     cmpb    options, 00H    ;any options?
  212.        jne     c5              ;yes, skip label
  213.        mov     ah, @prnstr     ;print label for char count
  214.        mov     dx, offset(char_label)
  215.        int     21H
  216.        jmps    c5a             ;print count
  217.  
  218. c5:     testb   options, C      ;/c option?
  219.        jz      c6              ;nope, skip
  220. c5a:    mov     di, chigh       ;get doubleword char count
  221.        mov     si, clow        ; in di:si
  222.        call    printdd         ;convert and print it
  223.        call    newline
  224.  
  225. c6:     ret
  226.  
  227. word_label db 'Words:  $'
  228. line_label db 'Lines:  $'
  229. char_label db 'Chars:  $'
  230. output    endp
  231.  
  232. ;=========================
  233. ; SUBROUTINE NEWLINE
  234. ; Prints a CR/LF to stdout
  235. ;=========================
  236. newline proc   near
  237.        mov     ah, @prnstr
  238.        mov     dx, offset(crlf)
  239.        int     21H
  240.        ret
  241. crlf   db      0DH, 0AH, '$'
  242. newline    endp
  243.  
  244. ;=========================================================
  245. ; SUBROUTINE PRINTDD
  246. ; This less-than-comprehensible routine was swiped verbatim
  247. ; from Ted Reuss's disassembly of John Chapman's sorted
  248. ; disk directory program.  The routine converts a 32 bit
  249. ; integer in DI:SI to ASCII digits and sends them to STDOUT.
  250. ;==========================================================